message: In BaseGPUDeviceFactory::CreateDevices() move the check for no GPU devices a little earlier.
  This saves ~83MiB of GPU DRAM for each (unused) GPU device, and some CPU heap memory allocated
  by libcuda.
diff: @@ -917,16 +917,21 @@ Status BaseGPUDeviceFactory::CreateDevices(const SessionOptions& options,
  }
  const auto& gpu_options = options.config.gpu_options();
  std::vector<CudaGpuId> visible_gpu_order;
  + std::vector<CudaGpuId> valid_cuda_gpu_ids;
  + // If we aren't going to use any GPUs, don't initialize them.
  + // We don't want to call ParseVisibleDeviceList if num_gpus_to_use is 0,
  + // because it treats an empty gpu_options.visible_device_list as 'all GPUs are
  + // visible'.
  + if (num_gpus_to_use > 0) {
  TF_RETURN_IF_ERROR(ParseVisibleDeviceList(gpu_options.visible_device_list(),
  &visible_gpu_order));
  -
  - std::vector<CudaGpuId> valid_cuda_gpu_ids;
  - TF_RETURN_IF_ERROR(GetValidDeviceIds(visible_gpu_order, &valid_cuda_gpu_ids));
  + TF_RETURN_IF_ERROR(
  + GetValidDeviceIds(visible_gpu_order, &valid_cuda_gpu_ids));
  + }
  if (num_gpus_to_use > valid_cuda_gpu_ids.size()) {
  num_gpus_to_use = valid_cuda_gpu_ids.size();
  }
  - // If we aren't going to use any GPUs, don't initialize them.
  - if (num_gpus_to_use > 0 && !valid_cuda_gpu_ids.empty()) {
  + if (!valid_cuda_gpu_ids.empty()) {
  // Save the original device.
  int original_device = 0;
  cudaError_t err = cudaGetDevice(&original_device);
  