title: How does the `my_input_fn` in the getting started with TensorFlow allow enumeration over the data?
body: <p>I'm looking at <a href="https://colab.research.google.com/notebooks/mlcc/first_steps_with_tensor_flow.ipynb?hl=en#scrollTo=yP92XkzhU803" rel="noreferrer">first steps with tensor flow</a> as part of the <a href="https://developers.google.com/machine-learning/crash-course/" rel="noreferrer">google machine learning crahs course</a> and already confused. My understanding is (please correct me if I'm wrong):</p>
  
  <ul>
  <li>Step 4 defines an input function <code>my_input_fn</code> that formats the data into the relevant TensorFlow structuresTensor</li>
  <li>Step 5 then supplies this function into the <code>train</code> call. </li>
  <li>The intention is that the train call will make successive calls to <code>my_input_fn</code> to get successive batches of data to adjust the model on. (??? vert suspect on this now)</li>
  </ul>
  
  <p><code>my_input_fn</code> is defined here:</p>
  
  <pre><code>def my_input_fn(features, targets, batch_size=1, shuffle=True, num_epochs=None):
      """Trains a linear regression model of one feature.
  
      Args:
        features: pandas DataFrame of features
        targets: pandas DataFrame of targets
        batch_size: Size of batches to be passed to the model
        shuffle: True or False. Whether to shuffle the data.
        num_epochs: Number of epochs for which data should be repeated. None = repeat indefinitely
      Returns:
        Tuple of (features, labels) for next data batch
      """
  
      # Convert pandas data into a dict of np arrays.
      features = {key:np.array(value) for key,value in dict(features).items()}                                           
  
      # Construct a dataset, and configure batching/repeating
      ds = Dataset.from_tensor_slices((features,targets)) # warning: 2GB limit
      ds = ds.batch(batch_size).repeat(num_epochs)
  
      # Shuffle the data, if specified
      if shuffle:
        ds = ds.shuffle(buffer_size=10000)
  
      # Return the next batch of data
      features, labels = ds.make_one_shot_iterator().get_next()
      return features, labels
  </code></pre>
  
  <p>From my reading of <code>my_input_fn</code>, I don't understand how this happens. I only have a rudimentary knowledge of python but my reading of the function is that every call to it will re-initialise the tensor structures from the pandas frames, get an iterator and then return the first element of it. Every time it is called. Sure, in the case of this example, if the data is shuffled (which it is by default) and the dataset is big it's <em>unlikely</em> you'll get duplicates for a step of 100, but this smells of sloppy programming (i.e. in the case it isn't shuffled it would always return the same first training data set) so I doubt this is the case.</p>
  
  <p>My next suspicion is that the <code>one_shot_iterator().get_next()</code> call is doing some interesting/wacky/tricky stuff. Like returning some sort of late eval structure that will allow the <code>train</code> function to enumerate to the next batch from itself as opposed to re-invoking <code>my_input_fn</code>?</p>
  
  <p>But honestly I'd like to clarify this because at this stage more hours than I care to think about later I am not any closer to understanding.</p>
  
  <p>My attempts to research have just led to further confusion.</p>
  
  <p>The tutorial suggests reading <a href="https://www.tensorflow.org/get_started/datasets_quickstart#passing_input_fn_data_to_your_model" rel="noreferrer">this</a> - at one point it this says "The train, evaluate, and predict methods of every Estimator require input functions to return a (features, label) pair containing tensorflow tensors.". Okay, this is inline with my original thoughts. Basically the example and label packaged in TensorFlow structures. </p>
  
  <p>But then it shows the results of what it returns and it is stuff like this (example):</p>
  
  <pre><code>({
      'SepalLength': &lt;tf.Tensor 'IteratorGetNext:2' shape=(?,) dtype=float64&gt;,
      'PetalWidth': &lt;tf.Tensor 'IteratorGetNext:1' shape=(?,) dtype=float64&gt;,
      'PetalLength': &lt;tf.Tensor 'IteratorGetNext:0' shape=(?,) dtype=float64&gt;,
      'SepalWidth': &lt;tf.Tensor 'IteratorGetNext:3' shape=(?,) dtype=float64&gt;},
  Tensor("IteratorGetNext_1:4", shape=(?,), dtype=int64))
  </code></pre>
  
  <p>In the code lab, <code>my_input_fn(my_feature, targets)</code> returns:</p>
  
  <pre><code>({'total_rooms': &lt;tf.Tensor 'IteratorGetNext:0' shape=(?,) dtype=float64&gt;},
  </code></pre>
  
  <p>)</p>
  
  <p>I have NO IDEA what to make of this. My reading of <a href="https://www.tensorflow.org/programmers_guide/tensors" rel="noreferrer">tensors</a> does not mention anything like this. I don't even know how to BEGIN interrogating this with my rudimentary Python and non-existent TensorFlow knowledge.</p>
  
  <p>The documentation for the <a href="https://www.tensorflow.org/api_docs/python/tf/contrib/data/Dataset#make_one_shot_iterator" rel="noreferrer">one shot iterator</a> says it creates an iterator for enumerating the elements. Again, this is in line with my thinking.</p>
  
  <p>The <a href="https://www.tensorflow.org/api_docs/python/tf/data/Iterator#get_next" rel="noreferrer">get_next</a> documentation says:</p>
  
  <blockquote>
    <p>Returns a nested structure of tf.Tensors containing the next element.</p>
  </blockquote>
  
  <p>I don't know how to parse this. What sort of nested structure? I mean it looks like a tuple but why wouldn't you just say tuple? What dictates this? Where is it described? Surely it is important?</p>
  
  <p>What am I misunderstanding here?</p>
  
  <p>(For a course that purportedly requires no prior knowledge of TensorFlow, the google machine learning crash course is making me feel pretty moronic. I'm genuinely curious as to how others in my situation are going with this.)</p>