Using tf.unpack when first dimension of Variable is None
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
tf.unpack (renamed to tf.unstack in TensorFlow 1.0+) splits a tensor along a given axis into a list of sub-tensors. It fails when the dimension along the split axis is None (unknown at graph construction time) because TensorFlow cannot determine how many tensors to produce. The fix is to use tf.unstack with an explicit num argument, or switch to tf.split or dynamic indexing with tf.gather which handle dynamic shapes naturally.
The Error
tf.unstack needs to know the number of output tensors at graph construction time. When the dimension is None, it cannot determine this.
Fix 1: Specify the num Argument
If you know the maximum number of elements at coding time, pass it explicitly:
This is rigid. The actual input must match the num value exactly.
Fix 2: Use tf.split with Dynamic Shape
tf.split can work with dynamic shapes when you specify the split sizes:
However, tf.split with a dynamic num_or_size_splits still returns a dynamic number of outputs, which limits what you can do statically.
Fix 3: Use tf.gather for Dynamic Indexing (Recommended)
Instead of unstacking, index into the tensor dynamically:
Fix 4: Use tf.map_fn for Per-Element Operations
tf.map_fn handles dynamic batch sizes because it processes elements one at a time using a tf.while_loop internally:
Fix 5: Use tf.while_loop for Custom Iteration
For more complex per-element logic with dynamic dimensions:
TensorFlow 2.x (Eager Execution)
In TensorFlow 2.x with eager execution, dynamic shapes work naturally:
For truly dynamic batch sizes in TF2, use tf.map_fn or vectorized operations:
Migration: tf.unpack to tf.unstack
Common Pitfalls
- Forgetting
numargument:tf.unstackwithoutnumon a dimension ofNonealways fails. Either providenumor usetf.map_fn/tf.gatherinstead. nummismatch at runtime: If you setnum=32but feed a batch of 16, TensorFlow raises a runtime shape error. Only usenumwhen the dimension is truly fixed.- Using
tf.unstackwhere vectorized ops work: Operations likex * 2,tf.nn.relu(x), andtf.matmulalready operate batch-wise. Unstacking, processing, and restacking is slower than vectorized computation. - TF1 vs TF2 confusion: In TF1 graph mode, shapes must be known at graph construction. In TF2 eager mode, shapes are resolved at runtime.
tf.unstackworks in TF2 eager mode withoutnumbecause the shape is known. - TensorArray performance:
tf.while_loopwithTensorArrayadds overhead compared to vectorized operations. Use it only when per-element logic cannot be expressed as batch operations.
Summary
tf.unstack(formerlytf.unpack) fails onNonedimensions because it cannot determine the output count at graph time- Pass
num=Ntotf.unstackwhen you know the exact dimension size - Use
tf.map_fnfor per-element operations with dynamic batch sizes - Use
tf.gatheror indexing (x[i]) for accessing specific elements - In TensorFlow 2.x with eager execution, dynamic shapes are handled naturally
- Prefer vectorized operations over unstacking whenever possible for better performance

