...
    @overload
    def __getitem__(self, item: slice) -> Tuple[Iterator[T], ...]:
        ...
    def __getitem__(
        self, item: Union[int, slice]
    ) -> Union[Iterator[T], Tuple[Iterator[T], ...]]:
        return self._children[item]
    def __iter__(self) -> Iterator[Iterator[T]]:
        yield from self._children
    def __enter__(self) -> "Tee[T]":
        return self
    def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> Literal[False]:
        self.close()
        return False
[docs]    def close(self) -> None:
        for child in self._children:
            child.close()
# Why this is needed https://stackoverflow.com/a/44638570
safetee = Tee
[docs]def batch_iterate(size: int, iterable: Iterable[T]) -> Iterator[List[T]]:
    """Utility batching function."""
    it = iter(iterable)
    while True:
        chunk = list(islice(it, size))
        if not chunk:
            return
        yield chunk