class_docstr: Variable getter which caches variables on the least loaded device.
  
  Variables smaller than a certain threshold are cached on a single specific
  device, as specified in the constructor. All other variables are load balanced
  across a pool of devices, by caching each variable on the least loaded device.
code: def __call__(self, getter, *args, **kwargs):
      size = tf.TensorShape(kwargs["shape"]).num_elements()
      if size is None or not kwargs.get("trainable", True):
          # TODO a lot of vars won't be saved then
          _replace_global_by_local(kwargs)
          return getter(*args, **kwargs)
  
      if size < self.small_variable_size_threshold:
          device_name = self.device_for_small_variables
      else:
          device_index, _ = min(
              enumerate(self.sizes), key=operator.itemgetter(1)
          )
          device_name = self.devices[device_index]
          self.sizes[device_index] += size
  
      kwargs["caching_device"] = device_name
      var = getter(*args, **kwargs)
      return var
  
imports: import operator
  from contextlib import contextmanager
  import tensorflow
  import threading
  from ..compat import tfv1
  from ..tfutils.common import get_tf_version_tuple
  from ..tfutils.scope_utils import cached_name_scope, under_name_scope
  from ..tfutils.varreplace import custom_getter_scope
  from ..utils import logger
  from ..utils.argtools import call_only_once
label_desc: Use image node_id 2 for calling the OverrideCachingDevice obj's underlying member method code with example usage: obj.__call__(getter) and returns: var, getter