title: parallelising tf.data.Dataset.from_generator with TF2.1
body: <p>They are already 2 posts about this topics, but they have not been updated for the recent TF2.1 release...</p>
  
  <p>In brief, I've got a lot of tif images to read and parse with a specific pipeline.  </p>
  
  <pre class="lang-py prettyprint-override"><code>import tensorflow as tf
  import numpy as np
  
  files = # a list of str
  labels = # a list of int
  n_unique_label = len(np.unique(labels))
  
  gen = functools.partial(generator, file_list=files, label_list=labels, param1=x1, param2=x2)
  dataset = tf.data.Dataset.from_generator(gen, output_types=(tf.float32, tf.int32))
  dataset = dataset.map(lambda b, c: (b, tf.one_hot(c, depth=n_unique_label)))
  </code></pre>
  
  <p>This processing works well. Nevertheless, I need to parallelize the file parsing part, trying the following solution:</p>
  
  <pre class="lang-py prettyprint-override"><code>files = # a list of str
  files = tensorflow.data.Dataset.from_tensor_slices(files)
  
  def wrapper(file_path):
      parser = partial(tif_parser, param1=x1, param2=x2)
      return tf.py_function(parser, inp=[file_path], Tout=[tf.float32])
  
  dataset = files.map(wrapper, num_parallel_calls=2)
  </code></pre>
  
  <p>The difference is that I parse one file at a time here with the <code>parser</code> function. However, but it does not work:</p>
  
  <pre class="lang-py prettyprint-override"><code>  File "loader.py", line 643, in tif_parser
      image = numpy.array(Image.open(file_path)).astype(float)
  
    File "python3.7/site-packages/PIL/Image.py", line 2815, in open
      fp = io.BytesIO(fp.read())
  
  AttributeError: 'tensorflow.python.framework.ops.EagerTensor' object has no attribute 'read'
  
  
       [[{{node EagerPyFunc}}]] [Op:IteratorGetNextSync]
  </code></pre>
  
  <p>As far as I understand, the <code>tif_parser</code> function does not receive a string but an (unevaluated) tensor. At now, this function is fairly simple:</p>
  
  <pre class="lang-py prettyprint-override"><code>def tif_parser(file_path, param1=1, param2=2):
      image = numpy.array(Image.open(file_path)).astype(float)
      image /= 255.0
  
      return image
  </code></pre>