Where deep learning's magic actually happens
Automatic differentiation is the engine behind training. tf.GradientTape records (on a tape) every operation involving watched tensors during a forward pass. When you call tape.gradient(target, source), it plays the tape backward — applying the chain rule automatically — and returns the gradient.
The default rule: tf.Variables are watched automatically. Plain tensors and tf.constant are not; you must call tape.watch(c) explicitly to compute a gradient w.r.t. them. This default exists because Variables are the trainable parameters — almost always what you want gradients for.
If tape.gradient(loss, weight) returns None, the variable wasn't used in the forward pass — there's no path connecting it to the loss. Either you froze the layer, you used tf.stop_gradient somewhere, or there's a bug in your model code.