class_docstr: A model of the expected behavior of a variable.
  
  The purpose of this model is to
  - Define, as simply as possible, the API and expected semantics of
    the Variable data structure.
  - Serve as a reference implementation for model-based testing
    of more sophisticated Variable data structures.
  
  Conceptually, a Variable is a batch of stacks, which admits masked
  reading and writing to the top element, and masked pushing and
  popping to save and restore previous writes. We model push as
  inserting an undefined value as the new top. This admits
  implementations that optimize push-pop sequences that do not have an
  interposing assignment.
  
  This model accepts and enforces a maximum stack depth, because I
  expect (some?) implementations that pre-allocate fixed-size arrays
  to hold their stacks.
  
  This model also chooses to require non-empty stacks, because that's
  convenient for the first implementation under test. It would have
  been equally valid to permit empty stacks, as long as they are not
  read from or written to before the next push.
docstr: Pushes each indicated stack, making room for a new write.
  
  The new top value is not defined (i.e., this need not be a
  "duplicating push").
  
  Args:
    mask: Boolean array of shape `[batch_size]`. The values at `True`
      indices of `mask` are updated; the others remain.
  
  Returns:
    var: Updated variable. `self` may be mutated.
  
  Raises:
    ValueError: If a push exceeds the maximum stack depth.
code: def push(self, mask):
      """Pushes each indicated stack, making room for a new write.
  
      The new top value is not defined (i.e., this need not be a
      "duplicating push").
  
      Args:
        mask: Boolean array of shape `[batch_size]`. The values at `True`
          indices of `mask` are updated; the others remain.
  
      Returns:
        var: Updated variable. `self` may be mutated.
  
      Raises:
        ValueError: If a push exceeds the maximum stack depth.
      """
      for should_modify, stack in zip(mask, self._stacks):
          if should_modify and len(stack) >= self._max_stack_depth:
              raise ValueError("Maximum stack depth exceeded.")
      for should_modify, stack in zip(mask, self._stacks):
          if should_modify:
              stack.append(None)
      return self
  
file_path: probability/tensorflow_probability/python/experimental/auto_batching/backend_test_lib.py
imports: from absl import logging
label_desc: Use image node_id 4 for calling the ModelVariable obj's underlying member method code with example usage: obj.push(mask) and returns: self