Fix most of the issues with the CNTK backend's random functions mentioned in #10594
diff --git a/keras/backend/cntk_backend.py b/keras/backend/cntk_backend.py
index a738b7ec16c..c12ad502088 100644
--- a/keras/backend/cntk_backend.py
+++ b/keras/backend/cntk_backend.py
@@ -369,27 +369,21 @@ def constant(value, dtype=None, shape=None, name=None):
 
 
 def random_binomial(shape, p=0.0, dtype=None, seed=None):
-    # use numpy workaround now
     if seed is None:
         # ensure that randomness is conditioned by the Numpy RNG
         seed = np.random.randint(10e7)
-        np.random.seed(seed)
     if dtype is None:
         dtype = np.float32
     else:
         dtype = _convert_string_dtype(dtype)
 
-    size = 1
     for _ in shape:
         if _ is None:
             raise ValueError('CNTK Backend: randomness op with '
                              'dynamic shape is not supported now. '
                              'Please provide fixed dimension '
                              'instead of `None`.')
-        size *= _
-
-    binomial = np.random.binomial(1, p, size).astype(dtype).reshape(shape)
-    return variable(value=binomial, dtype=dtype)
+    return C.random.bernoulli(shape=shape, dtype=dtype, mean=p, seed=seed)
 
 
 def random_uniform(shape, minval=0.0, maxval=1.0, dtype=None, seed=None):
@@ -400,7 +394,10 @@ def random_uniform(shape, minval=0.0, maxval=1.0, dtype=None, seed=None):
                              'Please provide fixed dimension '
                              'instead of `None`.')
 
-    return random_uniform_variable(shape, minval, maxval, dtype, seed)
+    if seed is None:
+        # ensure that randomness is conditioned by the Numpy RNG
+        seed = np.random.randint(10e3)
+    return C.random.uniform(shape=shape, dtype=dtype, low=minval, high=maxval, seed=seed)
 
 
 def random_uniform_variable(shape, low, high,
@@ -450,13 +447,14 @@ def random_normal_variable(
     if name is None:
         name = ''
 
-    return C.parameter(
+    p = C.parameter(
         shape=shape,
         init=C.initializer.normal(
             scale=scale,
             seed=seed),
         dtype=dtype,
         name=name)
+    return variable(value=p.value + mean)
 
 
 def random_normal(shape, mean=0.0, stddev=1.0, dtype=None, seed=None):
@@ -468,8 +466,10 @@ def random_normal(shape, mean=0.0, stddev=1.0, dtype=None, seed=None):
                              'dynamic shape is not supported now. '
                              'Please provide fixed dimension '
                              'instead of `None`.')
-    # how to apply mean and stddev
-    return random_normal_variable(shape=shape, mean=mean, scale=1.0, seed=seed)
+    if seed is None:
+        # ensure that randomness is conditioned by the Numpy RNG
+        seed = np.random.randint(10e3)
+    return C.random.normal(shape=shape, mean=mean, scale=stddev, seed=seed, dtype=dtype)
 
 
 def truncated_normal(shape, mean=0.0, stddev=1.0, dtype=None, seed=None):
diff --git a/tests/keras/backend/backend_test.py b/tests/keras/backend/backend_test.py
index 3ad37f5bf2a..ed049d10827 100644
--- a/tests/keras/backend/backend_test.py
+++ b/tests/keras/backend/backend_test.py
@@ -1162,13 +1162,19 @@ def legacy_test_pool3d(self):
                                       strides=(1, 1, 1), padding='same', pool_mode='avg')
 
     def test_random_normal(self):
-        mean = 0.
-        std = 1.
+        # test standard normal as well as a normal with a different set of parameters
         for k in BACKENDS:
-            rand = k.eval(k.random_normal((300, 200), mean=mean, stddev=std, seed=1337))
-            assert rand.shape == (300, 200)
-            assert np.abs(np.mean(rand) - mean) < 0.015
-            assert np.abs(np.std(rand) - std) < 0.015
+            for mean, std in [(0., 1.), (-10., 5.)]:
+                rand = k.eval(k.random_normal((300, 200), mean=mean, stddev=std, seed=1337))
+                assert rand.shape == (300, 200)
+                assert np.abs(np.mean(rand) - mean) < std * 0.015
+                assert np.abs(np.std(rand) - std) < std * 0.015
+
+                # test that random_normal also generates different values when used within a function
+                r = k.random_normal((1,), mean=mean, stddev=std, seed=1337)
+                samples = [k.eval(r) for _ in range(60000)]
+                assert np.abs(np.mean(samples) - mean) < std * 0.015
+                assert np.abs(np.std(samples) - std) < std * 0.015
 
     def test_random_uniform(self):
         min_val = -1.
@@ -1177,8 +1183,14 @@ def test_random_uniform(self):
             rand = k.eval(k.random_uniform((200, 100), min_val, max_val))
             assert rand.shape == (200, 100)
             assert np.abs(np.mean(rand)) < 0.015
-            assert np.max(rand) <= max_val
-            assert np.min(rand) >= min_val
+            assert max_val - 0.015 < np.max(rand) <= max_val
+            assert min_val + 0.015 > np.min(rand) >= min_val
+
+            r = k.random_uniform((1,), minval=min_val, maxval=max_val)
+            samples = [k.eval(r) for _ in range(20000)]
+            assert np.abs(np.mean(samples)) < 0.015
+            assert max_val - 0.015 < np.max(samples) <= max_val
+            assert min_val + 0.015 > np.min(samples) >= min_val
 
     def test_random_binomial(self):
         p = 0.5
@@ -1189,6 +1201,12 @@ def test_random_binomial(self):
             assert np.max(rand) == 1
             assert np.min(rand) == 0
 
+            r = k.random_binomial((1,), p)
+            samples = [k.eval(r) for _ in range(20000)]
+            assert np.abs(np.mean(samples) - p) < 0.015
+            assert np.max(samples) == 1
+            assert np.min(samples) == 0
+
     def test_truncated_normal(self):
         mean = 0.
         std = 1.

This addresses all of the issues in #10594 except for the problem with `truncated_normal`.