code: def build_reparam_kl_loss_and_gradients(inference, var_list):
      """Build loss function. Its automatic differentiation
      is a stochastic gradient of
  
      .. math::
  
        -\\text{ELBO} =  - ( \mathbb{E}_{q(z; \lambda)} [ \log p(x \mid z) ]
              + \\text{KL}(q(z; \lambda) \| p(z)) )
  
      based on the reparameterization trick [@kingma2014auto].
  
      It assumes the KL is analytic.
  
      Computed by sampling from $q(z;\lambda)$ and evaluating the
      expectation using Monte Carlo sampling.
      """
      p_log_lik = [0.0] * inference.n_samples
      base_scope = tf.get_default_graph().unique_name("inference") + "/"
      for s in range(inference.n_samples):
          # Form dictionary in order to replace conditioning on prior or
          # observed variable with conditioning on a specific value.
          scope = base_scope + tf.get_default_graph().unique_name(
              "sample"
          )
          dict_swap = {}
          for x, qx in six.iteritems(inference.data):
              if isinstance(x, RandomVariable):
                  if isinstance(qx, RandomVariable):
                      qx_copy = copy(qx, scope=scope)
                      dict_swap[x] = qx_copy.value()
                  else:
                      dict_swap[x] = qx
  
          for z, qz in six.iteritems(inference.latent_vars):
              # Copy q(z) to obtain new set of posterior samples.
              qz_copy = copy(qz, scope=scope)
              dict_swap[z] = qz_copy.value()
  
          for x in six.iterkeys(inference.data):
              if isinstance(x, RandomVariable):
                  x_copy = copy(x, dict_swap, scope=scope)
                  p_log_lik[s] += tf.reduce_sum(
                      inference.scale.get(x, 1.0)
                      * x_copy.log_prob(dict_swap[x])
                  )
  
      p_log_lik = tf.reduce_mean(p_log_lik)
  
      kl_penalty = tf.reduce_sum(
          [
              tf.reduce_sum(
                  inference.kl_scaling.get(z, 1.0)
                  * kl_divergence(qz, z)
              )
              for z, qz in six.iteritems(inference.latent_vars)
          ]
      )
  
      reg_penalty = tf.reduce_sum(tf.losses.get_regularization_losses())
  
      if inference.logging:
          tf.summary.scalar(
              "loss/p_log_lik",
              p_log_lik,
              collections=[inference._summary_key],
          )
          tf.summary.scalar(
              "loss/kl_penalty",
              kl_penalty,
              collections=[inference._summary_key],
          )
          tf.summary.scalar(
              "loss/reg_penalty",
              reg_penalty,
              collections=[inference._summary_key],
          )
  
      loss = -(p_log_lik - kl_penalty - reg_penalty)
  
      grads = tf.gradients(loss, var_list)
      grads_and_vars = list(zip(grads, var_list))
      return loss, grads_and_vars
  
imports: from __future__ import absolute_import
  from __future__ import division
  from __future__ import print_function
  import six
  import tensorflow
  from edward.inferences.variational_inference import VariationalInference
  from edward.models import RandomVariable
  from edward.util import copy, get_descendants
label_desc: Use image node_id 2 for calling a global function with example usage: build_reparam_kl_loss_and_gradients(inference, var_list) and returns: loss,  grads_and_vars