class_docstr: Abstract nD convolution layer (private, used as implementation base).
  
  This layer creates a convolution kernel that is convolved
  (actually cross-correlated) with the layer input to produce a tensor of
  outputs. It may also include a bias addition and activation function
  on the outputs. It assumes the `kernel` and/or `bias` are drawn from
  distributions.
  
  By default, the layer implements a stochastic forward pass via
  sampling from the kernel and bias posteriors,
  ```none
  outputs = f(inputs; kernel, bias), kernel, bias ~ posterior
  ```
  where f denotes the layer's calculation. It uses the Flipout
  estimator [(Wen et al., 2018)][1], which performs a Monte Carlo approximation
  of the distribution integrating over the `kernel` and `bias`. Flipout uses
  roughly twice as many floating point operations as the reparameterization
  estimator but has the advantage of significantly lower variance.
  
  The arguments permit separate specification of the surrogate posterior
  (`q(W|x)`), prior (`p(W)`), and divergence for both the `kernel` and `bias`
  distributions.
  
  #### References
  
  [1]: Yeming Wen, Paul Vicol, Jimmy Ba, Dustin Tran, and Roger Grosse. Flipout:
       Efficient Pseudo-Independent Weight Perturbations on Mini-Batches. In
       _International Conference on Learning Representations_, 2018.
       https://arxiv.org/abs/1803.04386
class_docstr_tok: ["Abstract","nD","convolution","layer","(","private",",","used","as","implementation","base",")",".","This","layer","creates","a","convolution","kernel","that","is","convolved","(","actually","cross-correlated",")","with","the","layer","input","to","produce","a","tensor","of","outputs",".","It","may","also","include","a","bias","addition","and","activation","function","on","the","outputs",".","It","assumes","the","`","kernel","`","and\/or","`","bias","`","are","drawn","from","distributions",".","By","default",",","the","layer","implements","a","stochastic","forward","pass","via","sampling","from","the","kernel","and","bias","posteriors",",","``","`","none","outputs","=","f","(","inputs",";","kernel",",","bias",")",",","kernel",",","bias","~","posterior","``","`","where","f","denotes","the","layer","'s","calculation",".","It","uses","the","Flipout","estimator","[","(","Wen","et","al.",",","2018",")","]","[","1","]",",","which","performs","a","Monte","Carlo","approximation","of","the","distribution","integrating","over","the","`","kernel","`","and","`","bias","`",".","Flipout","uses","roughly","twice","as","many","floating","point","operations","as","the","reparameterization","estimator","but","has","the","advantage","of","significantly","lower","variance",".","The","arguments","permit","separate","specification","of","the","surrogate","posterior","(","`","q","(","W|x",")","`",")",",","prior","(","`","p","(","W",")","`",")",",","and","divergence","for","both","the","`","kernel","`","and","`","bias","`","distributions",".","#","#","#","#","References","[","1","]",":","Yeming","Wen",",","Paul","Vicol",",","Jimmy","Ba",",","Dustin","Tran",",","and","Roger","Grosse",".","Flipout",":","Efficient","Pseudo-Independent","Weight","Perturbations","on","Mini-Batches",".","In","_International","Conference","on","Learning","Representations_",",","2018.","https",":","\/\/arxiv.org\/abs\/1803.04386"]
code: def _apply_variational_kernel(self, inputs):
      if not isinstance(
          self.kernel_posterior, independent_lib.Independent
      ) or not isinstance(
          self.kernel_posterior.distribution, normal_lib.Normal
      ):
          raise TypeError(
              "`{}` requires "
              "`kernel_posterior_fn` produce an instance of "
              "`tfd.Independent(tfd.Normal)` "
              '(saw: "{}").'.format(
                  type(self).__name__, self.kernel_posterior.name
              )
          )
      self.kernel_posterior_affine = normal_lib.Normal(
          loc=tf.zeros_like(self.kernel_posterior.distribution.loc),
          scale=self.kernel_posterior.distribution.scale,
      )
      self.kernel_posterior_affine_tensor = (
          self.kernel_posterior_tensor_fn(self.kernel_posterior_affine)
      )
      self.kernel_posterior_tensor = None
  
      outputs = self._convolution_op(
          inputs, self.kernel_posterior.distribution.loc
      )
  
      input_shape = tf.shape(inputs)
      batch_shape = tf.expand_dims(input_shape[0], 0)
      if self.data_format == "channels_first":
          channels = input_shape[1]
      else:
          channels = input_shape[-1]
  
      seed_stream = SeedStream(self.seed, salt="ConvFlipout")
  
      sign_input = tfp_random.rademacher(
          tf.concat([batch_shape, tf.expand_dims(channels, 0)], 0),
          dtype=inputs.dtype,
          seed=seed_stream(),
      )
      sign_output = tfp_random.rademacher(
          tf.concat([batch_shape, tf.expand_dims(self.filters, 0)], 0),
          dtype=inputs.dtype,
          seed=seed_stream(),
      )
  
      if self.data_format == "channels_first":
          for _ in range(self.rank):
              sign_input = tf.expand_dims(
                  sign_input, -1
              )  # 2D ex: (B, C, 1, 1)
              sign_output = tf.expand_dims(sign_output, -1)
      else:
          for _ in range(self.rank):
              sign_input = tf.expand_dims(
                  sign_input, 1
              )  # 2D ex: (B, 1, 1, C)
              sign_output = tf.expand_dims(sign_output, 1)
  
      perturbed_inputs = (
          self._convolution_op(
              inputs * sign_input, self.kernel_posterior_affine_tensor
          )
          * sign_output
      )
  
      outputs += perturbed_inputs
      return outputs
  
imports: import tensorflow.compat.v2
  from tensorflow_probability.python import random
  from tensorflow_probability.python.distributions import independent
  from tensorflow_probability.python.distributions import kullback_leibler
  from tensorflow_probability.python.distributions import normal
  from tensorflow_probability.python.internal import docstring_util
  from tensorflow_probability.python.internal import tf_keras
  from tensorflow_probability.python.layers import util
  from tensorflow_probability.python.util.seed_stream import SeedStream
  from tensorflow.python.ops import nn_ops
label_desc: Use image node_id 2 for calling the _ConvFlipout obj's underlying member method code with example usage: obj._apply_variational_kernel(inputs) and returns: outputs