[tf.data] Fix memory leak when not all elements of a `Dataset.from_generator()` are consumed.
This change introduces a new C++ Dataset implementation
(`GeneratorDataset`) that takes three functions:
1. An initialization function that is called before the first use.
2. A "get next" function that is called to produce the elements, until a call
raises the OutOfRange error.
3. A finalization function that is called before the iterator is destroyed.
Previously, the generator state would only be cleaned up if the caller
consumed *every* element of the generator. In the new version, the
finalization function ensures that the Python-side state of the
generator is released regardless of how the iterator is disposed.
Fixes #16163.
PiperOrigin-RevId:
186360401