class_docstr: PS Synchronizer.
  
  Synchronizes gradient updates using a Parameter Server.
  
  For in-graph synchronization, this just aggregates gradients on a worker's CPU.
  
  For between-graph synchronization, this aggregates gradients on a pre-defined
  (defined in the Strategy) parameter server.
  
  To keep this gradient aggregation in sync, the chief gives each worker a token
  for each variable for the workers to mark when their variable update is complete.
docstr: Apply between-graph synchronization to the target ops in the graph.
  
  Args:
      graph_item: The current graph.
      var_name: the variable to be synchronized.
  
  Returns:
      graph_item.GraphItem: updated graph item.
docstr_tok: ["Apply","between-graph","synchronization","to","the","target","ops","in","the","graph",".","Args",":","graph_item",":","The","current","graph",".","var_name",":","the","variable","to","be","synchronized",".","Returns",":","graph_item.GraphItem",":","updated","graph","item","."]
code: def between_graph_apply(self, graph_item, var_name):
      """
      Apply between-graph synchronization to the target ops in the graph.
  
      Args:
          graph_item: The current graph.
          var_name: the variable to be synchronized.
  
      Returns:
          graph_item.GraphItem: updated graph item.
      """
      if not self._sync:
          return graph_item
      item = graph_item
      # here the variable on replica:0 has been shared, so the original var_name won't work
      var_op_name = ops.prepend_name_scope(
          get_op_name(var_name), replica_prefix(0)
      )
      item.updated = True
      gradient, target, update_op = item.var_op_name_to_grad_info_v2[
          var_op_name
      ]
      with item.graph.as_default():
          proxy = (
              self._create_proxy(item, gradient, target)
              if self._local_replication
              else None
          )
          if proxy:
              proxy.update_colocation_group(item.get_colocation_op)
          with item.graph.name_scope(self._BETWEEN_GRAPH_APPLY_SCOPE):
              (
                  self._var_op_to_agg_grad,
                  self._var_op_to_accum_apply_op,
              ) = self._get_accumulation_ops(
                  item,
                  gradient,
                  target,
                  1 if self._staleness > 0 else self.num_workers,
              )
              self.add_sync_op(item, update_op, proxy)
          item.graph._names_in_use.pop(self._BETWEEN_GRAPH_APPLY_SCOPE)
      return item
  
imports: from functools import partial
  from typing import List
  from tensorflow.python import ops
  from tensorflow.python.framework import device_spec, dtypes, constant_op
  from tensorflow.python.platform import tf_logging
  from tensorflow.python.ops import math_ops, data_flow_ops, gen_control_flow_ops, control_flow_ops, gen_math_ops, gen_array_ops
  from autodist.const import MAX_INT64, AUTODIST_PREFIX
  from autodist.kernel.common import utils, variable_utils
  from autodist.kernel.common.op_info import UPDATE_OP_VAR_POS
  from autodist.kernel.common.proxy_variable import ProxyVariable
  from autodist.kernel.common.utils import get_op_name, get_consumers, get_ancestors, traverse, update_consumers, update_control_consumers, replica_prefix, strip_replica_prefix, get_control_consumers, remove_from_control_consumers, get_index_from_tensor_name, update_colocation_group
  from autodist.kernel.common.variable_utils import get_read_var_ops
  from autodist.kernel.synchronization.synchronizer import Synchronizer
  from autodist.proto import synchronizers_pb2
label_desc: Use image node_id 7 for calling the PSSynchronizer obj's underlying member method code with example usage: obj.between_graph_apply(graph_item, var_name) and returns: item, graph_item