title: Tensorflow: why is zip() function used in the steps involving applying the gradients?
body: <p>I am working through Assignment 6 of the Udacity Deep Learning course. I am unsure why the zip() function is used in these steps to apply the gradients. </p>
  
  <p>Here is the relevant code: </p>
  
  <pre><code># define the loss function
  logits = tf.nn.xw_plus_b(tf.concat(0, outputs), w, b) 
  loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits, tf.concat(0, train_labels)))
  
  # Optimizer.
  
  global_step = tf.Variable(0)
  #staircase=True means that the learning_rate updates at discrete time steps
  learning_rate = tf.train.exponential_decay(10.0, global_step, 5000, 0.1, staircase=True)
  optimizer = tf.train.GradientDescentOptimizer(learning_rate)
  
  gradients, v = zip(*optimizer.compute_gradients(loss))
  gradients, _ = tf.clip_by_global_norm(gradients, 1.25)
  optimizer = optimizer.apply_gradients(zip(gradients, v), global_step=global_step)
  </code></pre>
  
  <p>What is the purpose of applying the <code>zip()</code> function? </p>
  
  <p>Why is <code>gradients</code> and <code>v</code> stored that way? I thought <code>zip(*iterable)</code> returned just one zip object. </p>