diff --git a/include/aidge/filler/Filler.hpp b/include/aidge/filler/Filler.hpp
index c7b12a35c9167feebaa75ffa6f59d96f6476a6ef..51d01d87f338d1c8eb33b7b3ec6194390bfe13bf 100644
--- a/include/aidge/filler/Filler.hpp
+++ b/include/aidge/filler/Filler.hpp
@@ -41,12 +41,10 @@ enum VarianceNorm { FanIn, Average, FanOut };
 template <typename T>
 void constantFiller(std::shared_ptr<Tensor> tensor, T constantValue);
 
-// TODO: Keep template or use switch case depending on Tensor datatype ?
 template <typename T>
 void normalFiller(std::shared_ptr<Tensor> tensor, double mean = 0.0,
                   double stdDev = 1.0);
 
-// TODO: Keep template or use switch case depending on Tensor datatype ?
 template <typename T>
 void uniformFiller(std::shared_ptr<Tensor> tensor, T min, T max);
 
diff --git a/include/aidge/utils/Random.hpp b/include/aidge/utils/Random.hpp
index 704609c0c778c7065a580b86fc67aea7e9d3525d..73cbd1453b3d840d6da2c58eadd5c5f47e9e9070 100644
--- a/include/aidge/utils/Random.hpp
+++ b/include/aidge/utils/Random.hpp
@@ -9,23 +9,53 @@
  *
  ********************************************************************************/
 
-
 #ifndef AIDGE_RANDOM_H_
 #define AIDGE_RANDOM_H_
 
-
 #include <algorithm>
-#include <vector>
 #include <random>
+#include <vector>
+namespace Aidge {
 
 namespace Random {
 
-    void randShuffle(std::vector<unsigned int>& vec) {
-        std::random_device rd;
-        std::mt19937 g(rd());
-        std::shuffle(vec.begin(), vec.end(), g);
-    }
-
+/**
+ * @brief Generator is a class created to handle only one Mersenne Twister
+ * pseudo-random number generator for the whole Aidge framework.
+ *
+ * All of its method are static. You can set a random seed and access the
+ * generator.
+ * By default, the random seed is set to 0 but selected randomly.
+ *
+ */
+class Generator {
+   public:
+    /**
+     * @brief Set a seed to the pseudo-random number generator.
+     *
+     * @return std::mt19937&
+     */
+    static void setSeed(unsigned int seed);
+    static unsigned int getSeed() { return seed; };
+    /**
+     * @brief Return a Mersenne Twister pseudo-random number generator.
+     * You can set the seed of this generator using ``setSeed`` method.
+     *
+     * @return std::mt19937&
+     */
+    static std::mt19937& get() { return generator; };
+
+   private:
+    // Mersenne Twister pseudo-random number generator
+    static std::mt19937 generator;
+    static unsigned int seed;
+};
+
+inline void randShuffle(std::vector<unsigned int>& vec) {
+    std::shuffle(vec.begin(), vec.end(), Aidge::Random::Generator::get());
 }
 
-#endif //AIDGE_RANDOM_H_
\ No newline at end of file
+}  // namespace Random
+}  // namespace Aidge
+
+#endif  // AIDGE_RANDOM_H_
diff --git a/python_binding/pybind_core.cpp b/python_binding/pybind_core.cpp
index 80f0cc44f8f85e042bb8c2ce2cef3d8bba9099a2..5ffa8f6b460b720581fb8196d45ad84e1ef350f2 100644
--- a/python_binding/pybind_core.cpp
+++ b/python_binding/pybind_core.cpp
@@ -16,6 +16,7 @@
 namespace py = pybind11;
 
 namespace Aidge {
+void init_Random(py::module&);
 void init_Data(py::module&);
 void init_Database(py::module&);
 void init_DataProvider(py::module&);
@@ -73,6 +74,8 @@ void init_TensorUtils(py::module&);
 void init_Filler(py::module&);
 
 void init_Aidge(py::module& m) {
+    init_Random(m);
+
     init_Data(m);
     init_Database(m);
     init_DataProvider(m);
diff --git a/python_binding/utils/pybind_Random.cpp b/python_binding/utils/pybind_Random.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a1956d2d1e398cdb81673e7760a92bcde46e2de6
--- /dev/null
+++ b/python_binding/utils/pybind_Random.cpp
@@ -0,0 +1,24 @@
+/********************************************************************************
+ * Copyright (c) 2023 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#include <pybind11/pybind11.h>
+#include "aidge/utils/Random.hpp"
+
+namespace py = pybind11;
+
+namespace Aidge {
+
+void init_Random(py::module &m) {
+    auto mRand = m.def_submodule("random", "Random module.");
+    py::class_<Random::Generator>(mRand, "Generator")
+    .def_static("set_seed", Random::Generator::setSeed);
+}
+}  // namespace Aidge
diff --git a/src/data/DataProvider.cpp b/src/data/DataProvider.cpp
index 7783ed86cf4ae1d8672cc6a35a97ca9a996457b6..5c3d1d7ef3b3dd8c779cf9cda737f1a2b2f6e01f 100644
--- a/src/data/DataProvider.cpp
+++ b/src/data/DataProvider.cpp
@@ -41,8 +41,8 @@ Aidge::DataProvider::DataProvider(const Aidge::Database& database, const std::si
     }
 
     // Compute the number of bacthes depending on mDropLast boolean
-    mNbBatch = (mDropLast) ? 
-                static_cast<std::size_t>(std::floor(mNbItems / mBatchSize)) : 
+    mNbBatch = (mDropLast) ?
+                static_cast<std::size_t>(std::floor(mNbItems / mBatchSize)) :
                 static_cast<std::size_t>(std::ceil(mNbItems / mBatchSize));
 }
 
@@ -98,7 +98,7 @@ std::vector<std::shared_ptr<Aidge::Tensor>> Aidge::DataProvider::readBatch() con
 
 
 void Aidge::DataProvider::setBatches(){
-    
+
     mBatches.clear();
     mBatches.resize(mNbItems);
     std::iota(mBatches.begin(),
@@ -106,7 +106,7 @@ void Aidge::DataProvider::setBatches(){
               0U);
 
     if (mShuffle){
-        Random::randShuffle(mBatches);
+        Aidge::Random::randShuffle(mBatches);
     }
 
     if (mNbItems % mBatchSize !=0){ // The last batch is not full
diff --git a/src/filler/HeFiller.cpp b/src/filler/HeFiller.cpp
index e49386b49c3829c5657a155ac5e6fdddf40f9c03..74d681f1a05c15045d27a0fe678aa676d16af077 100644
--- a/src/filler/HeFiller.cpp
+++ b/src/filler/HeFiller.cpp
@@ -13,6 +13,7 @@
 
 #include "aidge/data/Tensor.hpp"
 #include "aidge/filler/Filler.hpp"
+#include "aidge/utils/Random.hpp"
 
 template <typename T>
 void Aidge::heFiller(std::shared_ptr<Aidge::Tensor> tensor,
@@ -36,9 +37,6 @@ void Aidge::heFiller(std::shared_ptr<Aidge::Tensor> tensor,
                      ? meanNorm / ((fanIn + fanOut) / 2.0)
                      : meanNorm / fanOut);
 
-    std::random_device rd;
-    std::mt19937 gen(rd());  // Mersenne Twister pseudo-random number generator
-
     std::normal_distribution<T> normalDist(mean, stdDev);
 
     std::shared_ptr<Tensor> cpyTensor;
@@ -48,7 +46,7 @@ void Aidge::heFiller(std::shared_ptr<Aidge::Tensor> tensor,
 
     // Setting values
     for (std::size_t idx = 0; idx < tensorWithValues.size(); ++idx) {
-        tensorWithValues.set<T>(idx, scaling*normalDist(gen));
+        tensorWithValues.set<T>(idx, scaling*normalDist(Aidge::Random::Generator::get()));
     }
 
     // Copy values back to the original tensors (actual copy only if needed)
diff --git a/src/filler/NormalFiller.cpp b/src/filler/NormalFiller.cpp
index 0fadbd134ff9fd4712a57541cfb3f35debdff13d..f30b32431cf466b10c1b10df8e0e5ccec9f483b6 100644
--- a/src/filler/NormalFiller.cpp
+++ b/src/filler/NormalFiller.cpp
@@ -13,6 +13,7 @@
 
 #include "aidge/data/Tensor.hpp"
 #include "aidge/filler/Filler.hpp"
+#include "aidge/utils/Random.hpp"
 
 template <typename T>
 void Aidge::normalFiller(std::shared_ptr<Aidge::Tensor> tensor, double mean,
@@ -20,8 +21,6 @@ void Aidge::normalFiller(std::shared_ptr<Aidge::Tensor> tensor, double mean,
     AIDGE_ASSERT(tensor->getImpl(),
                  "Tensor got no implementation, cannot fill it.");
     AIDGE_ASSERT(NativeType<T>::type == tensor->dataType(), "Wrong data type");
-    std::random_device rd;
-    std::mt19937 gen(rd());  // Mersenne Twister pseudo-random number generator
 
     std::normal_distribution<T> normalDist(mean, stdDev);
 
@@ -32,7 +31,7 @@ void Aidge::normalFiller(std::shared_ptr<Aidge::Tensor> tensor, double mean,
 
     // Setting values
     for (std::size_t idx = 0; idx < tensorWithValues.size(); ++idx) {
-        tensorWithValues.set<T>(idx, normalDist(gen));
+        tensorWithValues.set<T>(idx, normalDist(Aidge::Random::Generator::get()));
     }
 
     // Copy values back to the original tensors (actual copy only if needed)
diff --git a/src/filler/UniformFiller.cpp b/src/filler/UniformFiller.cpp
index e45d6f13edeadd8261cbe9742fc064bbcd6155c1..a942f59d717fd8d7b541ee28868a7fb9f2e7cd95 100644
--- a/src/filler/UniformFiller.cpp
+++ b/src/filler/UniformFiller.cpp
@@ -13,14 +13,14 @@
 
 #include "aidge/data/Tensor.hpp"
 #include "aidge/filler/Filler.hpp"
+#include "aidge/utils/Random.hpp"
 
 template <typename T>
 void Aidge::uniformFiller(std::shared_ptr<Aidge::Tensor> tensor, T min, T max) {
     AIDGE_ASSERT(tensor->getImpl(),
                  "Tensor got no implementation, cannot fill it.");
     AIDGE_ASSERT(NativeType<T>::type == tensor->dataType(), "Wrong data type");
-    std::random_device rd;
-    std::mt19937 gen(rd());  // Mersenne Twister pseudo-random number generator
+
 
     std::uniform_real_distribution<T> uniformDist(min, max);
 
@@ -31,7 +31,7 @@ void Aidge::uniformFiller(std::shared_ptr<Aidge::Tensor> tensor, T min, T max) {
 
     // Setting values
     for (std::size_t idx = 0; idx < tensorWithValues.size(); ++idx) {
-        tensorWithValues.set<T>(idx, uniformDist(gen));
+        tensorWithValues.set<T>(idx, uniformDist(Aidge::Random::Generator::get()));
     }
 
     // Copy values back to the original tensors (actual copy only if needed)
diff --git a/src/filler/XavierFiller.cpp b/src/filler/XavierFiller.cpp
index f1c5d17e80d1f683b59a6429407d74f69000e321..a1de15971ca8063e504e270fa6d2275d93270460 100644
--- a/src/filler/XavierFiller.cpp
+++ b/src/filler/XavierFiller.cpp
@@ -13,10 +13,11 @@
 
 #include "aidge/data/Tensor.hpp"
 #include "aidge/filler/Filler.hpp"
+#include "aidge/utils/Random.hpp"
 
 template <typename T>
-void Aidge::xavierUniformFiller(std::shared_ptr<Aidge::Tensor> tensor, T scaling,
-                         Aidge::VarianceNorm varianceNorm) {
+void Aidge::xavierUniformFiller(std::shared_ptr<Aidge::Tensor> tensor,
+                                T scaling, Aidge::VarianceNorm varianceNorm) {
     AIDGE_ASSERT(tensor->getImpl(),
                  "Tensor got no implementation, cannot fill it.");
     AIDGE_ASSERT(NativeType<T>::type == tensor->dataType(), "Wrong data type");
@@ -30,9 +31,6 @@ void Aidge::xavierUniformFiller(std::shared_ptr<Aidge::Tensor> tensor, T scaling
                   : fanOut);
     const T scale(std::sqrt(3.0 / n));
 
-    std::random_device rd;
-    std::mt19937 gen(rd());  // Mersenne Twister pseudo-random number generator
-
     std::uniform_real_distribution<T> uniformDist(-scale, scale);
 
     std::shared_ptr<Aidge::Tensor> cpyTensor;
@@ -41,8 +39,8 @@ void Aidge::xavierUniformFiller(std::shared_ptr<Aidge::Tensor> tensor, T scaling
         tensor->refCastFrom(cpyTensor, tensor->dataType(), "cpu");
     // Setting values
     for (std::size_t idx = 0; idx < tensorWithValues.size(); ++idx) {
-        T value = scaling * uniformDist(gen);
-        tensorWithValues.set<T>(idx, value);
+        tensorWithValues.set<T>(
+            idx, scaling * uniformDist(Aidge::Random::Generator::get()));
     }
 
     // Copy values back to the original tensors (actual copy only if needed)
@@ -50,7 +48,7 @@ void Aidge::xavierUniformFiller(std::shared_ptr<Aidge::Tensor> tensor, T scaling
 }
 template <typename T>
 void Aidge::xavierNormalFiller(std::shared_ptr<Aidge::Tensor> tensor, T scaling,
-                        Aidge::VarianceNorm varianceNorm) {
+                               Aidge::VarianceNorm varianceNorm) {
     AIDGE_ASSERT(tensor->getImpl(),
                  "Tensor got no implementation, cannot fill it.");
     AIDGE_ASSERT(NativeType<T>::type == tensor->dataType(), "Wrong data type");
@@ -64,9 +62,6 @@ void Aidge::xavierNormalFiller(std::shared_ptr<Aidge::Tensor> tensor, T scaling,
                   : fanOut);
     const double stdDev(std::sqrt(1.0 / n));
 
-    std::random_device rd;
-    std::mt19937 gen(rd());  // Mersenne Twister pseudo-random number generator
-
     std::normal_distribution<T> normalDist(0.0, stdDev);
 
     std::shared_ptr<Aidge::Tensor> cpyTensor;
@@ -76,7 +71,8 @@ void Aidge::xavierNormalFiller(std::shared_ptr<Aidge::Tensor> tensor, T scaling,
 
     // Setting values
     for (std::size_t idx = 0; idx < tensorWithValues.size(); ++idx) {
-        tensorWithValues.set<T>(idx, scaling*normalDist(gen));
+        tensorWithValues.set<T>(
+            idx, scaling * normalDist(Aidge::Random::Generator::get()));
     }
 
     // Copy values back to the original tensors (actual copy only if needed)
diff --git a/src/utils/Random.cpp b/src/utils/Random.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e3716f4fc4e271ba06316f40ffa7227ccfa2cb03
--- /dev/null
+++ b/src/utils/Random.cpp
@@ -0,0 +1,22 @@
+/********************************************************************************
+ * Copyright (c) 2023 CEA-List
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+#include "aidge/utils/Random.hpp"
+
+#include <random>  // normal_distribution, uniform_real_distribution
+
+std::mt19937 Aidge::Random::Generator::generator{std::random_device{}()};
+unsigned int Aidge::Random::Generator::seed = 0;
+
+void Aidge::Random::Generator::setSeed(unsigned int seed) {
+    seed = seed;
+    generator.seed(seed);
+}