code: def make_conv2d_layer_class(strides, padding):
      """Creates a `Conv2DLayer` class.
  
      Args:
        strides: A 2-tuple of positive integers. Strides for the spatial dimensions.
        padding: A Python string. Can be either 'SAME' or 'VALID'.
  
      Returns:
        conv2d_layer_class: A new `Conv2DLayer` class that closes over the args to
          this function.
      """
  
      # TODO(siege): We do this rather than storing parameters explicitly inside the
      # class because we want to avoid having to use a CompositeTensor-like
      # functionality, as that requires annotating a large porting of TFP with
      # expand_composites=True. This isn't worth doing for this experimental
      # library.
  
      class Conv2DLayer(
          collections.namedtuple(
              "Conv2DLayer",
              [
                  "kernel",
              ],
          )
      ):
          """2-dimensional convolution (in the standard deep learning sense) layer.
  
          See `tf.nn.conv` for the mathematical details of what this does.
  
          Attributes:
            kernel: A floating point Tensor with shape `[width, height, in_channels,
              out_channels]`.
          """
  
          __slots__ = ()
  
          @property
          def strides(self):
              """Strides for the spatial dimensions."""
              return strides
  
          @property
          def padding(self):
              """Padding."""
              return padding
  
          def __call__(self, x):
              """Applies the layer to an input.
  
              Args:
                x: A floating point Tensor with shape `[batch, height, width,
                  in_channels]`.
  
              Returns:
                y: A floating point Tensor with shape `[batch, height', width',
                  out_channels]`. The output `width'` and `height'` depend on the value
                  of
                  `padding`.
              """
  
              @functools.partial(
                  vectorization_util.make_rank_polymorphic,
                  core_ndims=(4, 4),
              )
              # In an ideal world we'd broadcast the kernel shape with the batch shape
              # of the input, but the hardware does not like that.
              def do_conv(kernel, x):
                  return tf.nn.conv2d(
                      x,
                      filters=kernel,
                      strides=(1,) + self.strides + (1,),
                      padding=self.padding,
                  )
  
              return do_conv(self.kernel, x)
  
      return Conv2DLayer
  
imports: import collections
  import functools
  import tensorflow.compat.v2
  from tensorflow_probability.python.distributions import deterministic
  from tensorflow_probability.python.distributions import joint_distribution_coroutine
  from tensorflow_probability.python.distributions import normal
  from tensorflow_probability.python.distributions import sample
  from tensorflow_probability.python.internal import vectorization_util
label_desc: Use image node_id 2 for calling a global function with example usage: make_conv2d_layer_class(strides, padding) and returns: Conv2DLayer, strides, padding, do_conv, tf