function fusedDepthwiseConv2d_(_ref) {
	  var x = _ref.x,
	      filter = _ref.filter,
	      strides = _ref.strides,
	      pad = _ref.pad,
	      _ref$dataFormat = _ref.dataFormat,
	      dataFormat = _ref$dataFormat === void 0 ? 'NHWC' : _ref$dataFormat,
	      _ref$dilations = _ref.dilations,
	      dilations = _ref$dilations === void 0 ? [1, 1] : _ref$dilations,
	      dimRoundingMode = _ref.dimRoundingMode,
	      bias = _ref.bias,
	      _ref$activation = _ref.activation,
	      activation = _ref$activation === void 0 ? 'linear' : _ref$activation,
	      preluActivationWeights = _ref.preluActivationWeights,
	      leakyreluAlpha = _ref.leakyreluAlpha;

	  if (shouldFuse(ENGINE.state.gradientDepth, activation) === false) {
	    var result = depthwiseConv2d(x, filter, strides, pad, dataFormat, dilations, dimRoundingMode);

	    if (bias != null) {
	      result = add$1(result, bias);
	    }

	    return applyActivation(result, activation, preluActivationWeights, leakyreluAlpha);
	  }

	  var $x = convertToTensor(x, 'x', 'depthwiseConv2d');
	  var $filter = convertToTensor(filter, 'filter', 'depthwiseConv2d');
	  var x4D = $x;
	  var reshapedTo4D = false;

	  if ($x.rank === 3) {
	    reshapedTo4D = true;
	    x4D = reshape($x, [1, $x.shape[0], $x.shape[1], $x.shape[2]]);
	  }

	  assert(x4D.rank === 4, function () {
	    return "Error in fused depthwiseConv2d: input must be rank 4, but got " + ("rank " + x4D.rank + ".");
	  });
	  assert($filter.rank === 4, function () {
	    return "Error in fused depthwiseConv2d: filter must be rank 4, " + ("but got rank " + $filter.rank + ".");
	  });
	  assert(x4D.shape[3] === $filter.shape[2], function () {
	    return "Error in fused depthwiseConv2d: number of input channels " + ("(" + x4D.shape[3] + ") must match the inChannels dimension in ") + ("filter " + $filter.shape[2] + ".");
	  });

	  if (dilations == null) {
	    dilations = [1, 1];
	  }

	  assert(eitherStridesOrDilationsAreOne(strides, dilations), function () {
	    return 'Error in fused depthwiseConv2d: Either strides or dilations must ' + ("be 1. Got strides " + strides + " and dilations '" + dilations + "'");
	  });

	  if (dimRoundingMode != null) {
	    assert(isInt(pad), function () {
	      return "Error in fused depthwiseConv2d: pad must be an integer when " + ("using dimRoundingMode " + dimRoundingMode + " but got pad " + pad + ".");
	    });
	  }

	  var convInfo = computeConv2DInfo(x4D.shape, $filter.shape, strides, dilations, pad, dimRoundingMode, true
	  /* depthwise */
	  );
	  var $bias;

	  if (bias != null) {
	    $bias = convertToTensor(bias, 'bias', 'fused conv2d');

	    var _makeTypesMatch = makeTypesMatch($bias, $x);

	    $bias = _makeTypesMatch[0];
	    assertAndGetBroadcastShape(convInfo.outShape, $bias.shape);
	  }

	  var $preluActivationWeights;

	  if (preluActivationWeights != null) {
	    $preluActivationWeights = convertToTensor(preluActivationWeights, 'prelu weights', 'fused depthwiseConv2d');
	  }

	  var grad = function grad(dy, saved) {
	    assert(tupleValuesAreOne(dilations), function () {
	      return 'Error in gradient of fused depthwiseConv2d: dilation rates ' + "greater than 1 are not yet supported. Got dilations " + ("'" + dilations + "'");
	    });
	    var $filter = saved[0],
	        x4D = saved[1],
	        y = saved[2],
	        bias = saved[3];
	    var dyActivation = getFusedDyActivation(dy, y, activation);
	    var xDer = depthwiseConv2dNativeBackpropInput(x4D.shape, dyActivation, $filter, strides, pad, dilations, dimRoundingMode);
	    var filterDer = depthwiseConv2dNativeBackpropFilter(x4D, dyActivation, $filter.shape, strides, pad, dilations, dimRoundingMode);

	    if (bias != null) {
	      var biasDer = getFusedBiasGradient($bias, dyActivation);
	      return [xDer, filterDer, biasDer];
	    }

	    return [xDer, filterDer];
	  };

	  var inputs = {
	    x: x4D,
	    filter: $filter,
	    bias: $bias,
	    preluActivationWeights: $preluActivationWeights
	  };
	  var attrs = {
	    strides: strides,
	    pad: pad,
	    dataFormat: dataFormat,
	    dilations: dilations,
	    dimRoundingMode: dimRoundingMode,
	    activation: activation,
	    leakyreluAlpha: leakyreluAlpha
	  }; // Depending on the the params passed in we will have different number of
	  // inputs and thus a a different number of elements in the gradient.

	  if (bias == null) {
	    var customOp = customGrad(function (x4D, filter, save) {
	      // tslint:disable-next-line: no-unnecessary-type-assertion
	      var res = ENGINE.runKernel(FusedDepthwiseConv2D, inputs, attrs);
	      save([filter, x4D, res]);

	      if (reshapedTo4D) {
	        // tslint:disable-next-line: no-unnecessary-type-assertion
	        res = reshape(res, [res.shape[1], res.shape[2], res.shape[3]]);
	      }

	      return {
	        value: res,
	        gradFunc: grad
	      };
	    });
	    return customOp(x4D, $filter);
	  } else {
	    var customOpWithBias = customGrad(function (x4D, filter, bias, save) {
	      // tslint:disable-next-line: no-unnecessary-type-assertion
	      var res = ENGINE.runKernel(FusedDepthwiseConv2D, inputs, attrs);
	      save([filter, x4D, res, bias]);

	      if (reshapedTo4D) {
	        // tslint:disable-next-line: no-unnecessary-type-assertion
	        res = reshape(res, [res.shape[1], res.shape[2], res.shape[3]]);
	      }

	      return {
	        value: res,
	        gradFunc: grad
	      };
	    });
	    return customOpWithBias(x4D, $filter, $bias);
	  }
	}
Computes depthwise 2D convolution, optionally fused with adding a
bias and applying an activation.

Given a 4D `input` array and a `filter` array of shape
`[filterHeight, filterWidth, inChannels, channelMultiplier]` containing
`inChannels` convolutional filters of depth 1, this op applies a
different filter to each input channel (expanding from 1 channel to
`channelMultiplier` channels for each), then concatenates the results
together. The output has `inChannels * channelMultiplier` channels.

See
[https://www.tensorflow.org/api_docs/python/tf/nn/depthwise_conv2d](
    https://www.tensorflow.org/api_docs/python/tf/nn/depthwise_conv2d)
for more details.

@param obj An object with the following properties:
@param x The input tensor, of rank 4 or rank 3, of shape
    `[batch, height, width, inChannels]`. If rank 3, batch of 1 is
assumed.
@param filter The filter tensor, rank 4, of shape
    `[filterHeight, filterWidth, inChannels, channelMultiplier]`.
@param strides The strides of the convolution: `[strideHeight,
strideWidth]`. If strides is a single number, then `strideHeight ==
strideWidth`.
@param pad The type of padding algorithm.
  - `same` and stride 1: output will be of same size as input,
      regardless of filter size.
  - `valid`: output will be smaller than input if filter is larger
      than 1x1.
  - For more info, see this guide:
    [https://www.tensorflow.org/api_guides/python/nn#Convolution](
         https://www.tensorflow.org/api_guides/python/nn#Convolution)
@param dilations The dilation rates: `[dilationHeight, dilationWidth]`
    in which we sample input values across the height and width dimensions
    in atrous convolution. Defaults to `[1, 1]`. If `rate` is a single
    number, then `dilationHeight == dilationWidth`. If it is greater than
    1, then all values of `strides` must be 1.
@param dataFormat: An optional string from: "NHWC", "NCHW". Defaults to
    "NHWC". Specify the data format of the input and output data. With the
    default format "NHWC", the data is stored in the order of: [batch,
    height, width, channels]. Only "NHWC" is currently supported.
@param dimRoundingMode A string from: 'ceil', 'round', 'floor'. If none is
    provided, it will default to truncate.
@param bias Tensor to be added to the result.
@param activation Name of activation kernel (defaults to `linear`).
@param preluActivationWeights Tensor of prelu weights to be applied as part
    of a `prelu` activation, typically the same shape as `x`.
@param leakyreluAlpha Optional. Alpha to be applied as part of a `leakyrelu`
    activation.