Q:

Do TensorFlow optimizers learn gradients in a graph with assignments? 

I am reproducing the original paper of Elman networks (Elman, 1990) – together with Jordan networks, known as Simple Recurrent Networks (SRN).  As far as I can understand, my code correctly implements the forward propagation, while the learning phase is incomplete.  I am implementing the network using the low-level API of TensorFlow, in Python. 
The Elman network is an artificial neural network composed of two layers, where the hidden layer gets copied as a "context layer," which concatenates with the inputs the next time we run forward propagate the network.  Initially, the context layer is initialized with activation = 0.5 and has a fixed weight of 1.0. 

My question is on the calculation of gradients, in the backpropagation of the network.   In my code, I use tf.assign to update context units with the activations from the hidden layer.  Before adding the assignment operator to the graph, TensorBoard shows that GradientDescentOptimizer will learn gradients from all the variables in the graph.  After I include this statement, gradients don't show up for the variables in nodes coming "before" the assignment.  In other words, I would expect b_1, w_x, w_c, and a_1 to show up in the list of gradients learned by the optimizer, even with the assignment in the graph. 
I believe my implementation for the forward propagation is correct because I compared final values for activations using tf.assign and values from another implementation, using plain Numpy arrays.  The values are equal. 
Finally: is this behavior intentional or am I doing something wrong? 
Here's a notebook with the implementation of the network as I described:
https://gist.github.com/Irio/d00b9661023923be7c963395483dfd73
References
Elman, J. L. (1990).  Finding Structure in Time.  Cognitive Science, 14(2), 179–211.  Retrieved from https://crl.ucsd.edu/~elman/Papers/fsit.pdf

A:

No, assign operations do not backpropagate a gradient.  That is on purpose, as assigning a value to a variable is not a differentiable operation.  However, you probably do not want the gradient of the assignment, but the gradient of the new value of the variable.  You can use that gradient, just do not use it as the output of an assignment operation.  For example, you can do something like this:
import tensorflow as tf

my_var = tf. Variable(var_intial_value, name="MyVar")
# Compute new value for the variable
new_my_var = ...
# Make the assignment operation a control dependency
with tf.control_dependencies([tf.assign(my_var, new_my_var)]):
    # Passing the value through identity here will ensure assignment is done
    # while keeping it differentiable
    new_my_var = tf.identity(new_my_var)
# Continue using the value

This would mean that my_var is not used in the backpropagation, and so it will not be updated by an optimizer.  However, I suppose if you are assigning values to my_var yourself, then it should not be updated by the optimizer.